using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace NAst.Common
{
    /// <summary>
    /// Add a network drive
    /// </summary>
    [Netlet("ConnectNetworkDrive")]
    public class ConnectNetworkDriveNetlet : INetlet
    {
        #region Interop
        [DllImport("mpr.dll")]
        private static extern int WNetAddConnection2A(ref NetResource resource,string lpPassword,string lpUserName,uint dwFlags);
        private static void ConnectDrive(string drive, string netPath)
        {
            NetResource res = new NetResource();
            res.dwType = 1;
            res.lpLocalName = drive;
            res.lpRemoteName = netPath;
            int hr = WNetAddConnection2A(ref res, null, null, 1);
            switch(hr)
            {
                case 0 :
                    return;
                case 85:
                    DisconnectDrive(drive);
                    hr = WNetAddConnection2A(ref res, null, null, 1);
                    if(hr!=0)
                        throw new Win32Exception(hr);
                    return;
                default:
                    throw new Win32Exception(hr);
            }
        }


        [DllImport("mpr.dll")]
        private static extern int WNetCancelConnection2A([MarshalAs(UnmanagedType.LPStr)] string lpName, int dwFlags, bool fForce);
        private static void DisconnectDrive(string disk)
        {
            int hr = WNetCancelConnection2A(disk, 1, true);
            switch (hr)
            {
                case 0:
                    return;
                case 2250:
                    return;
                default:
                    throw new Win32Exception(hr);
            } 
        }

		[StructLayout(LayoutKind.Sequential)]
		private struct NetResource{
			public int dwScope;
			public int dwType;
			public int dwDisplayType;
			public int dwUsage;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpLocalName;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpRemoteName;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpComment;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpProvider;
		}
        #endregion

        private string _remotePath = null;
        private string _localDrive = null;

        #region INetlet Members

        public void Initialize(string stateName, System.Xml.XmlElement config)
        {
            _remotePath = config.GetAttribute("remotePath");
            _localDrive = config.GetAttribute("localDrive");
        }

        public void Connect()
        {
            ConnectDrive(_localDrive,_remotePath);
        }

        public void Disconnect()
        {
            if(!string.IsNullOrEmpty(_localDrive))
                DisconnectDrive(_localDrive);
        }

        public void SaveState(System.Xml.XmlElement elmToSaveTo)
        {
            elmToSaveTo.SetAttribute("localDrive", _localDrive);
        }

        public void LoadState(System.Xml.XmlElement elmToLoadFrom)
        {
            _localDrive = elmToLoadFrom.GetAttribute("localDrive");
        }

        #endregion
    }
}
